﻿using System;
using System.Collections.Generic;
using System.Linq;
using MdcService.Static;
using MdcService.Structure;
using MdcService.Structure.Enum;
using TitaniumAS.Opc.Client.Common;
using TitaniumAS.Opc.Client.Da;

namespace MdcService.Machine
{
	public class SinumerikMachine:BaseMachine,IDisposable
	{
		public override MachineType Type { get;  set; } = MachineType.Siunmerik;
		private Uri _url;
		private OpcDaServer _server;
		private OpcDaGroup _group;
		private List<OpcDaItemDefinition> _itemDefinitions = new List<OpcDaItemDefinition>();
		private OpcDaItemValue[] _itemValues;
		private Dictionary<string,ValueItem> _valueItemsDict = new Dictionary<string, ValueItem>();

		private string _path;

		public override string Path
		{
			get { return _path; }
		    set
			{
				//path:"PCU50|OPC.SINUMERIK.Machineswitch"
				_path = value;
				string[] urlStrings = _path.Split('@');
				if (urlStrings.Length != 2)
				{
					throw new ArgumentException($"Invaild path string :{_path}");
				}
				this._url = UrlBuilder.Build(urlStrings[0], urlStrings[1]);
			}
		}

		public SinumerikMachine()
		{
			
		}

		public override void Connect()
		{
		    _server = new OpcDaServer(this._url);
			Values.ForEach(i =>
			{
				_itemDefinitions.Add(new OpcDaItemDefinition
				{
					ItemId = i.Value.Path.Trim(),
					IsActive = true
				});
				_valueItemsDict.Add(i.Value.Path.Trim(),i.Value);
			});
			try
			{
				_server.Connect();
				_group = _server.AddGroup("MolyMadeGroup");
				_group.IsActive = true;
				_group.AddItems(_itemDefinitions);
				this.LastConnected = DateTime.Now;
				this.IsConnected = true;
				Failures = 0;
			}
			catch (Exception)
			{
				Failures = Failures > 100 ? 99 : Failures + 1;
				throw;
			}
		}

		public override void Disconnect()
		{
			if (IsConnected)
			{
				_server.Disconnect();
			}
		}

		public override void Read()
		{

			_itemValues = _group.Read(_group.Items, OpcDaDataSource.Device);
			foreach (OpcDaItemValue value in _itemValues)
			{
				if (_valueItemsDict.ContainsKey(value.Item.ItemId))
				{
					_valueItemsDict[value.Item.ItemId].Value = Utilities.SerializeObject(value.Value);
				}
			}
			this.LastRead = DateTime.Now;

		}

		public override void Dispose()
		{
			_server.Dispose();
		}

		public override string ToString()
		{
			return $"Opc machine ({this.Path}) with {Values.Count} tags";
		}
	}
}
